package org.yanse.structures.linkedList;

public class CircularLinkedList {
        private ListNode head;
        private int size;

        public CircularLinkedList() {
            head = null;
            size = 0;
        }

        public CircularLinkedList(int[] arrays) {
            if (arrays == null || arrays.length == 0) {
                head = null;
                size = 0;
                return;
            }

            head = new ListNode(arrays[0]);
            ListNode current = head;

            for (int i = 1; i < arrays.length; i++) {
                current.next = new ListNode(arrays[i]);
                current = current.next;
            }
            current.next = head;
            size = arrays.length;
        }

        public void printLinkedList() {
            if (head == null) {
                return;
            }
            ListNode current = head.next;
            System.out.print(head.val + " ");
            while (current != head) {
                System.out.print(current.val + " ");
                current = current.next;
            }
        }

        private ListNode getNode(int index) {
            if (index <= 0) {
                return head;
            }

            if (index > size - 1) {
                throw new IndexOutOfBoundsException();
            }

            ListNode current = head.next;
            int currentIndex = 1;
            while (current != head) {
                if (currentIndex == index) {
                    return current;
                }
                currentIndex++;
                current = current.next;
            }

            throw new NoSuchElementException();
        }

        public int get(int index) {
            return getNode(index).val;
        }

        public void add(int ele) {
            // 最后一个元素
            ListNode lastNode = getNode(size - 1);
            ListNode eleNode = new ListNode(ele);
            lastNode.next = eleNode;
            eleNode.next = head;
            size++;
        }

        public void set(int index, int ele) {
            getNode(index).val = ele;
        }

        public void remove(int index) {
            if (size == 0 || index > size - 1) {
                throw new NoSuchElementException();
            }

            if (size == 1) {
                head = null;
                size = 0;
                return;
            }
            ListNode lastNode = null;
            ListNode nextNode = null;

            if (index <= 0) {
                lastNode = getNode(size - 1);
                nextNode = head.next;
                head = nextNode;
            } else {
                lastNode = getNode(index - 1);
                nextNode = getNode(index).next;
            }
            lastNode.next = nextNode;
            size--;
        }

        public void reverse() {
            if (size < 2) {
                return;
            }
            ListNode current = head;
            ListNode lastNode = null;
            ListNode nextNode = null;
            while (current.next != head) {
                nextNode = current.next;
                current.next = lastNode;
                lastNode = current;
                current = nextNode;
            }
            current.next = lastNode;
            head.next = current;
            head = current;
        }

        public int size() {
            return size;
        }
}
